
/// 所有的迭代器都实现了标准库中的 Iterator trait
fn main() {
    let mut my_counter = Counter::new();
    println!("Value :: ======= {:?}", my_counter.next());

    let v1 = [1,3,5];
    let v2 = [2,4,6];

    // zip 方法将两个迭代器的值进行拼接合并，返回一个tuple
    for x in v1.iter().zip(v2.iter().skip(1)) {
        println!("=== > {:?}", x);
    }
}

// 自定义一个结构然后给其实现 Iterator 的 trait
struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Counter {
        Counter {
            count: 0
        }
    }
}

// 实例化迭代器
impl Iterator for Counter {
    // 定义了Item 的关联类型，实际上就是给某个类型起了一个别名。
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        if self.count >= 6 {
            None
        }else{
            self.count += 1;
            Some(self.count)
        }
    }
}

#[test] // 测试迭代器的zip 方法
fn using_other_iterator_trait_methods () {
    let sum: u32 = Counter::new().zip(Counter::new().skip(1))
        .map(|(a, b)| a * b) // 理论上 1*2=2，2*3=6，3*4=12，4*5=20，5*6=30
        .filter(|x|x % 3 == 0)// 理论上 6，12，30
        .sum(); // 6+12+30
    assert_eq!(48, sum);
}

#[test] //测试 Counter 类
fn self_iterator() {
    let mut my_counter = Counter::new();
    assert_eq!(Some(1u32), my_counter.next());
    assert_eq!(Some(2u32), my_counter.next());
    assert_eq!(Some(3u32), my_counter.next());
    assert_eq!(Some(4u32), my_counter.next());
    assert_eq!(Some(5u32), my_counter.next());
    assert_eq!(Some(6u32), my_counter.next());
    assert_eq!(None, my_counter.next());
}


#[test] // 如下测试可以通过
fn iterator_domonstration() {
    let v1 = vec![1, 2, 3];
    let mut v1_iter = v1.iter();

    // 从这里可看出迭代器返回的实际上是一个 Option<T>
    assert_eq!(Some(&1), v1_iter.next());
    assert_eq!(Some(&2), v1_iter.next());
    assert_eq!(Some(&3), v1_iter.next());
}

#[test] // 测试迭代器 sum 方法
fn iterator_sum() {
    // 迭代器求和的方法
    let v1 = vec![1,2,3];
    assert_eq!(6 , v1.iter().sum());

    // 如下的代码是不行的 ， 类型 S 不能关联到 sum 方法上。
    // let v2 = vec!["a".to_string(), "b".to_string(), "c".to_string()];
    // assert_eq!("abc", v2.iter().sum());
}

#[test] // 测试迭代器map 方法
fn iterator_map() {
    // 在迭代器上调用 map 本身并不难理解。
    // 但需要注意的是，调用迭代器的map 本身是惰性的。
    // 所以需要调用 collect 方法，它会消耗迭代器并将结果值收集到某种结合数据类型中。
    let v1 = vec![1,2,3];
    // 注意v2不要忘了定义类型
    let v2: Vec<_> = v1.iter().map(|  x| {x+1}).collect(); // 计划生成 2，3，4
    assert_eq!(v2, vec![2,3,4]);

    // 换种玩法试试，注意经过 map 后返回是 Some(2) 而不是 Some(&2)
    assert_eq!(Some(2), v1.iter().next().map(|x| {x + 1}));
    // 这样就不行了，我的理解还是有错误。
    // assert_eq!(Some(3), v1.iter().next().map(|x| {x + 1}));
    // assert_eq!(Some(4), v1.iter().next().map(|x| {x + 1}));
}

// 测试 filter 闭包函数，这个方法接受一个返回true false 的闭包
// 只有当闭包返回true 的时候才会被包含在filter 生成的新迭代器中。
#[test]
fn iterator_filter() {
    let v1 = vec![1,2,3,4,5,6,7,8,9];
    let v2: Vec<_> = v1.iter().filter(|x| ->bool {
        *x % 2 == 0
    }).collect();
    // 断言时候需要注意，filter 返回的是引用值，所以断言时候应该 vec[&2] 这种。
    assert_eq!(vec![&2,&4,&6,&8], v2);
}